package com.bloom.product.qms.sync;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.bloom.cloud.common.context.BaseContextHandler;
import com.bloom.cloud.core.db.DynamicDataSourceHolder;
import com.bloom.cloud.core.utils.DateUtils;
import com.bloom.cloud.processor.common.annotation.Executor;
import com.bloom.cloud.processor.common.annotation.ServiceExecutor;
import com.bloom.cloud.processor.common.model.TableColumnProps;
import com.bloom.cloud.processor.common.model.TsBusinessDefinition;
import com.bloom.cloud.processor.common.params.ServiceDefinitionParam;
import com.bloom.cloud.processor.common.params.ServiceInParam;
import com.bloom.cloud.processor.common.params.ServiceOutParam;
import com.bloom.cloud.processor.common.service.DynamicBaseExecutor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.text.SimpleDateFormat;
import java.util.*;

@ServiceExecutor(code = "QMS_DYNAMIC_SALE_RECORD_MQP_TO_QMS")
public class QMSDynamicSaleRecordMqpToQmsExecutor extends DynamicBaseExecutor {

    private static final Map<String, String> dayMapReversal = new HashMap<>();
    private static final Map<String, String> monthMapReversal = new HashMap<>();
    static {
        dayMapReversal.put("1", "01");
        dayMapReversal.put("2", "02");
        dayMapReversal.put("3", "03");
        dayMapReversal.put("4", "04");
        dayMapReversal.put("5", "05");
        dayMapReversal.put("6", "06");
        dayMapReversal.put("7", "07");
        dayMapReversal.put("8", "08");
        dayMapReversal.put("9", "09");
        dayMapReversal.put("A", "10");
        dayMapReversal.put("B", "11");
        dayMapReversal.put("C", "12");
        dayMapReversal.put("D", "13");
        dayMapReversal.put("E", "14");
        dayMapReversal.put("F", "15");
        dayMapReversal.put("G", "16");
        dayMapReversal.put("H", "17");
        dayMapReversal.put("J", "18");
        dayMapReversal.put("K", "19");
        dayMapReversal.put("L", "20");
        dayMapReversal.put("M", "21");
        dayMapReversal.put("N", "22");
        dayMapReversal.put("P", "23");
        dayMapReversal.put("Q", "24");
        dayMapReversal.put("R", "25");
        dayMapReversal.put("S", "26");
        dayMapReversal.put("T", "27");
        dayMapReversal.put("U", "28");
        dayMapReversal.put("X", "29");
        dayMapReversal.put("Y", "30");
        dayMapReversal.put("Z", "31");

        monthMapReversal.put("1", "01");
        monthMapReversal.put("2", "02");
        monthMapReversal.put("3", "03");
        monthMapReversal.put("4", "04");
        monthMapReversal.put("5", "05");
        monthMapReversal.put("6", "06");
        monthMapReversal.put("7", "07");
        monthMapReversal.put("8", "08");
        monthMapReversal.put("9", "09");
        monthMapReversal.put("X", "10");
        monthMapReversal.put("Y", "11");
        monthMapReversal.put("Z", "12");
    }

    public static String convertBatchNumberToDate(String batchNumber) {
        String regex = "^[0-9][1-9X-Z][1-9A-Z]$";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(batchNumber);

        if (!matcher.matches()) {
            return null;
        }
        String yearPart = batchNumber.substring(0, 1);
        String monthPart = batchNumber.substring(1, 2);
        String dayPart = batchNumber.substring(2, 3);

        // Check if yearPart is a digit
        if (!Character.isDigit(yearPart.charAt(0))) {
            return null;
        }
        int currentYear = java.time.Year.now().getValue();//1XA  2021-10-10
        int decadeStartYear = (currentYear / 10) * 10;
        int targetYear = decadeStartYear + Integer.parseInt(yearPart);
        if (targetYear > currentYear) {
            targetYear -= 10;
        }
        String month = monthMapReversal.getOrDefault(monthPart, "00");
        String day = dayMapReversal.getOrDefault(dayPart, "00");
        if ("00".equals(month) || "00".equals(day)) {
            return null;
            // Assert.notNull(null, batchNumber);
            // throw new IllegalArgumentException("Invalid month or day code in batch number.");
        }
        return String.format("%d-%s-%s", targetYear, month, day);
    }
    @Executor
    public ServiceOutParam execute(ServiceDefinitionParam param) {
        String system = param.getInParam().getInstance();
        HashMap<String, Object> rtnMap = new HashMap<>();
        ServiceInParam inParam = param.getInParam();
        int page = inParam.get("page") == null ? 1 : Integer.valueOf(inParam.get("page").toString());
        int size = inParam.get("size") == null ? 1000 : Integer.valueOf(inParam.get("size").toString());

        String startDate = "";
        if(inParam.get("start_date") == null){
            SimpleDateFormat dayFormat = new SimpleDateFormat("yyyy-MM-dd");
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(new Date());
            calendar.add(Calendar.DAY_OF_MONTH,-3);
            Date privateDate = calendar.getTime();
            startDate = dayFormat.format(privateDate);
        }else{
            startDate = String.valueOf(inParam.get("start_date"));
        }

        String instance = "qms";
        final String TT_SALE_RECORD_QMS = "TT_SALE_RECORD_QMS";
        TsBusinessDefinition definition = JSON.parseObject(super.configLoadService.getBusinessDefinitionByTableName(TT_SALE_RECORD_QMS, instance), TsBusinessDefinition.class);
        TableColumnProps columnProps = JSON.parseObject(super.configLoadService.getTableColumnPropsByTableName(TT_SALE_RECORD_QMS, instance), TableColumnProps.class);

        List<Map<String, Object>> saleRecordList = getSaleRecordInfo(system,page,size,startDate);


        if(saleRecordList != null && saleRecordList.size() > 0){
            //已有的mqp事件数据
            Set<String> eventSet = getExistSet(system,startDate);


            //产品信息
            Map<String,Map<String,Object>> productMap = getProductInfo(system);
//            Map<String,Map<String,Object>> companyMap = getCompanyInfo(system);
            Map<String,Map<String,Object>> defectMap = getDefectInfo(system);
            Map<String,Map<String,Object>> mainEnginePlantMap = getMainEnginePlantInfo(system);
            List<Map<String,Object>> saveList = new ArrayList<>();
            for(Map<String,Object> map : saleRecordList){
                String mqp_id = String.valueOf(map.get("id"));
                if(eventSet.add(mqp_id)){
                    Map<String,Object> dataMap = new HashMap<>();
                    dataMap.put("mqp_id",map.get("id"));

                    dataMap.put("back_month",map.get("back_month"));
                    dataMap.put("batch_code",map.get("batch_code"));
                    dataMap.put("claim_app_code",map.get("claim_app_code"));
                    dataMap.put("entrust_code",map.get("entrust_code"));
                    dataMap.put("guide_data",map.get("guide_data"));
                    dataMap.put("vim",map.get("vim"));
                    dataMap.put("code",map.get("code"));
                    dataMap.put("sys_code",map.get("sys_code"));
                    dataMap.put("unwork_part",map.get("unwork_part"));
                    dataMap.put("repair_time",map.get("repair_time"));
                    dataMap.put("buy_time",map.get("buy_time"));
                    dataMap.put("car_made_time",map.get("car_made_time"));
                    dataMap.put("customer_id",mainEnginePlantMap.containsKey(map.get("customer_code")+"") ? (mainEnginePlantMap.get(map.get("customer_code")+"") == null ? null:mainEnginePlantMap.get(map.get("customer_code")+"").get("id")):null);
                    dataMap.put("unique_code",map.get("unique_code"));
                    dataMap.put("mes_qr_id",map.get("mes_qr_id"));
                    dataMap.put("whether_tag",map.get("whether_tag"));
                    dataMap.put("drive_distance",map.get("drive_distance"));
                    dataMap.put("consumer_describe_all",map.get("consumer_describe_all"));
                    dataMap.put("consumer_describe_extract",map.get("consumer_describe_extract"));
                    dataMap.put("return_date",map.get("repair_time"));
                    dataMap.put("company_code",map.get("company_code"));

                    dataMap.put("material_id",productMap.containsKey(map.get("part_code")+"") ? productMap.get(map.get("part_code")+"").get("id"):null);
                    dataMap.put("defect_id",defectMap.containsKey(map.get("defect_code")+"") ? defectMap.get(map.get("defect_code")+"").get("id"):map.get("defect_id"));

                    Object batchCodeObj = map.get("batch_code");

                    String batchCode = batchCodeObj != null ? batchCodeObj.toString() : "";

                    if (StringUtils.isNotBlank(batchCode) && batchCode.length() == 3) {
                        dataMap.put("made_time", convertBatchNumberToDate(batchCode));
                    }else {
                        dataMap.put("made_time",map.get("made_time"));
                    }

                    dataMap.put("mes_part_code",map.get("part_code"));
                    dataMap.put("claim_cycle",map.get("claim_cycle"));

                    dataMap.put("repair_station_code",map.get("repair_station_code"));
                    dataMap.put("repair_station_name",map.get("repair_station_name"));
                    dataMap.put("up_part_code",map.get("up_part_code"));
                    dataMap.put("down_part_code",map.get("down_part_code"));

                    dataMap.put("whether_insure",map.get("whether_insure"));
                    dataMap.put("compare_mes_code",map.get("compare_mes_code"));
                    dataMap.put("first_analyse",map.get("first_analyse"));
                    dataMap.put("last_analyse",map.get("last_analyse"));
                    dataMap.put("responsibility_person",map.get("responsibility_person"));
                    dataMap.put("defect_part_go",map.get("defect_part_go"));
                    dataMap.put("use_months_category",map.get("use_months_category"));
                    dataMap.put("represent_record",map.get("represent_record"));
                    dataMap.put("represent_time",map.get("represent_time"));
                    dataMap.put("mark_time",map.get("mark_time"));
                    dataMap.put("represent_customer_reply_status",map.get("represent_customer_reply_status"));
                    dataMap.put("remark",map.get("remark"));
                    dataMap.put("represent_customer_reply_remark",map.get("represent_customer_reply_remark"));
                    dataMap.put("ocrfile",map.get("ocrfile"));
                    dataMap.put("base",map.get("base"));
                    dataMap.put("store_code",map.get("store_code"));

                    dataMap.put("created_at",map.get("created_at"));
                    dataMap.put("updated_at",map.get("updated_at"));
                    dataMap.put("created_by",map.get("created_by"));
                    dataMap.put("updated_by",map.get("updated_by"));
                    dataMap.put("removed",map.get("removed"));
                    if (StringUtils.isBlank(BaseContextHandler.getUserID())||"-1".equals(BaseContextHandler.getUserID())){
                        dataMap.put("create_user", 61);
                    }
                    saveList.add(dataMap);
                }
            }

            //Assert.notNull(null,JSONObject.toJSONString(saveList));

            if(saveList.size() > 0){
//                dynamicDataExecutor.saveBatch(saveList,columnPropsEvent,definitionEvent);
                saveList.stream().forEach(item ->{
                    dynamicDataExecutor.save(item,definition,columnProps);
                });
            }

        }
        return ServiceOutParam.success(rtnMap);
    }



    private List<Map<String, Object>> getSaleRecordInfo(String system,Integer page,Integer size,String create_time_start){
        Integer start = page == 0 ? 0: (page-1)*size;
        DynamicDataSourceHolder.setDbType(system+"_mqp");
        StringBuffer sql = new StringBuffer();
        sql.append(" select s.id,company_code,sys_code,s.code,back_month,s.customer_id,c.code as customer_code,c.name as customer_name,unique_code,up_part_code,down_part_code,repair_station_code,repair_station_name,  ");
        sql.append(" claim_app_code,entrust_code,vim,store_code,claim_cycle,buy_time,repair_time,drive_distance,whether_insure,guide_data,batch_code,consumer_describe_all,consumer_describe_extract,  ");
        sql.append(" compare_mes_code,whether_tag,remark,last_analyse,unwork_part,responsibility_person,defect_part_go,use_months_category,represent_record,represent_time,represent_customer_reply_status,s.created_by,s.created_at,s.updated_by,s.updated_at,s.removed,  ");
        sql.append(" base,made_time,mes_qr_id,represent_customer_reply_remark,car_made_time,ocrfile,mark_time,s.material_id,m.part_code,s.defect_id,d.defect_code,d.first_analyse from tt_sale_record s   ");
        sql.append(" left join tt_customer c on s.customer_id = c.id    ");
        sql.append(" left join tt_material m on s.material_id = m.id  ");
        sql.append(" left join tt_defect d on s.defect_id = d.id  ");
        sql.append(" where 1=1  ");
        if(StringUtils.isNotBlank(create_time_start)){
            sql.append(" and s.created_at >=   '"+create_time_start+"'");
        }
        sql.append(" limit " + start + "," + size);
        List<Map<String, Object>> saleInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        return saleInfoList;
    }

    private Set<String> getExistSet(String system,String create_time_start){
        DynamicDataSourceHolder.setDbType(system);
        StringBuffer sql = new StringBuffer();
        sql.append("  select id,mqp_id from tt_sale_record_qms where MARK_FOR_DELETE = 0 and mqp_id is not null and created_at >= '"+create_time_start+"'");
        List<Map<String, Object>> eventInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        Set<String> rtnSet = new HashSet<>();
        if(eventInfoList != null && eventInfoList.size() > 0){
            for(Map<String, Object> map : eventInfoList){
                rtnSet.add(String.valueOf(map.get("mqp_id")));
            }
        }
        return rtnSet;
    }

    private Map<String,Map<String,Object>> getCompanyInfo(String system){
        DynamicDataSourceHolder.setDbType(system);
        StringBuffer sql = new StringBuffer();
        sql.append("  select id,company_code,company_name from tm_company where mark_for_delete = 0 ");
        List<Map<String, Object>> companyInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        Map<String,Map<String,Object>> rtnMap = new HashMap<>();
        if(companyInfoList != null && companyInfoList.size() > 0){
            for(Map<String, Object> map : companyInfoList){
                rtnMap.put(String.valueOf(map.get("company_code")),map);
            }
        }
        return rtnMap;
    }

    private Map<String,Map<String,Object>> getDefectInfo(String system){
        DynamicDataSourceHolder.setDbType(system);
        StringBuffer sql = new StringBuffer();
        sql.append("  select id,defect_code from tt_mqp_defect where mark_for_delete = 0 ");
        List<Map<String, Object>> dataInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        Map<String,Map<String,Object>> rtnMap = new HashMap<>();
        if(dataInfoList != null && dataInfoList.size() > 0){
            for(Map<String, Object> map : dataInfoList){
                rtnMap.put(String.valueOf(map.get("defect_code")),map);
            }
        }
        return rtnMap;
    }

    private Map<String,Map<String,Object>> getMainEnginePlantInfo(String system){
        DynamicDataSourceHolder.setDbType(system);
        StringBuffer sql = new StringBuffer();
        sql.append("  select id,main_engine_plant_code,main_engine_plant_name from tm_main_engine_plant where MARK_FOR_DELETE = 0 ");
        List<Map<String, Object>> dataInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        Map<String,Map<String,Object>> rtnMap = new HashMap<>();
        if(dataInfoList != null && dataInfoList.size() > 0){
            for(Map<String, Object> map : dataInfoList){
                rtnMap.put(String.valueOf(map.get("main_engine_plant_code")),map);
            }
        }
        return rtnMap;
    }

    private Map<String,Map<String,Object>> getProductInfo(String system){
        DynamicDataSourceHolder.setDbType(system);
        StringBuffer sql = new StringBuffer();
        sql.append("  select id,name,assembly_code,engine_plant_id,engine_plant_code,engine_plant_name from tb_standard_assembly_product where MARK_FOR_DELETE = 0 ");
        List<Map<String, Object>> dataInfoList = dynamicDataExecutor.findAllSql(sql);
        DynamicDataSourceHolder.clearDBType();
        Map<String,Map<String,Object>> rtnMap = new HashMap<>();
        if(dataInfoList != null && dataInfoList.size() > 0){
            for(Map<String, Object> map : dataInfoList){
                rtnMap.put(String.valueOf(map.get("assembly_code")),map);
            }
        }
        return rtnMap;
    }
}
